#pragma once

#include<string>
#include<vector>
#include<fstream>
#include<sstream>
#include<iostream>

using namespace std;

#define Z_ATOMIC 0
#define Z_DOUHAO 1
#define Z_RET 2
#define Z_THREEYE 3
#define Z_GIVER 4
#define Z_LOGIC 5
#define Z_ADD_MATH 6
#define Z_MUL_MATH 7
#define Z_BIT_MATH 8
#define Z_ONEYE 9
#define Z_MEMGETER 10
#define Z_PandCALL 11
#define Z_ALPHT 12
#define Z_GJZ 13 

short prio(const string&str){
	if(str=="+"||str=="-"){
		return Z_ADD_MATH;
	}
	if(str[0]=='+'||str[0]=='-'||str[0]=='\''||str[0]=='\"'||(str[0]>='0'&&str[0]<='9')){
		return Z_ATOMIC;
	}
	if(str=="("||str==")"||str=="{"||str=="}"){
		return Z_PandCALL;
	}
	if(str=="."||str=="["||str=="]"){
		return Z_MEMGETER;
	}
	if(str=="=")return Z_GIVER;
	if(str=="let"||str=="mut"||str=="func"||str=="print"||str=="in"
		||str=="lock"||str=="typeof"||str=="if"||str=="exec"||str=="slice"||str=="exit")
		return Z_GJZ;
	if(str=="*"||str=="/"||str=="%")
		return Z_MUL_MATH;
	return Z_ALPHT;
}
struct token{
	string str;
	short wv;
	// 淇濈暀鍘熸瀯閫犲嚱鏁伴€昏緫
	token() : wv(0) {}
	token(const string &s) : str(s), wv(prio(s)) {}
};

class Words{
	public:
		vector<vector<token>> words;
		Words(){}
		Words(const string &str){
			load(str);
		}
		void load(const string &str){
			ifstream ifp(str);
			if(!ifp.is_open()){
				cerr<<"Error: Cannot open file "<<str<<endl;
				return;
			}
			string t;
			while(getline(ifp,t)){
				if(t.empty()) continue;
				if(t[0]=='$'){
					string sub_file = t.substr(1);
					load(sub_file);
					continue;
				}
				lexer(t);
			}
		}
		static char chcl(const char &a){
			if((a>='a'&&a<='z')||(a>='A'&&a<='Z')||(a>='0'&&a<='9')||a=='_'||a=='.'){
				return 'a';
			}
			if(a=='('||a==')'||a=='['||a==']'||a=='{'||a=='}'||a=='/'||a=='\"'||a==','){
				return a;
			}
			return 'o';
		}
		void lexer(const string &str){
			vector<token> wordss;
			char flag = 0;  // 0:鏈紑濮? 'a':瀛楁瘝鏁板瓧  '(':鎷彿绫? '"':瀛楃涓插唴  'o':鏅€氱鍙?
			string s;
			// 鏂板锛氭爣璁版槸鍚﹀浜庡瓧绗︿覆鍐呴儴锛堣В鍐冲紩鍙峰唴瀛楃绫诲瀷涓嶄腑鏂殑鏍稿績閫昏緫锛?
			bool in_string = false;

			for(auto &a:str){
				// 1. 澶勭悊绌烘牸锛氫粎鍦ㄩ潪瀛楃涓插唴閮ㄦ椂锛岀┖鏍煎垎闅攖oken
				if(a==' ' && !in_string){
					if(!s.empty()){
						wordss.push_back(token(s));
						s.clear();
					}
					flag = 0;
					continue;
				}

				// 2. 澶勭悊瀛楃涓插紩鍙凤細鍒囨崲瀛楃涓插唴閮ㄧ姸鎬?
				if(a=='"'){
					if(!s.empty()&&!in_string){
						wordss.push_back(token(s));
						s.clear();
					}
					s += a;  // 鎶婂紩鍙峰姞鍏ュ綋鍓峵oken
					in_string = !in_string;  // 杩涘叆/閫€鍑哄瓧绗︿覆妯″紡
					flag = '"';  // 鏍囪褰撳墠token涓哄瓧绗︿覆绫诲瀷
					// 鑻ラ€€鍑哄瓧绗︿覆锛堢浜屼釜寮曞彿锛夛紝鐩存帴淇濆瓨璇ュ瓧绗︿覆token
					if(!in_string){
						wordss.push_back(token(s));
						s.clear();
						flag = 0;
					}
					continue;
				}

				// 3. 瀛楃涓插唴閮ㄩ€昏緫锛氬拷鐣ュ瓧绗︾被鍨嬪樊寮傦紝鍏ㄩ儴鎷兼帴鍒板綋鍓峵oken
				if(in_string){
					s += a;
					continue;
				}

				// 4. 闈炲瓧绗︿覆鍖哄煙锛氭寜鍘熷瓧绗︾被鍨嬮€昏緫澶勭悊
				if(flag){
					if((flag != chcl(a))||flag==')'||flag=='('||flag=='['||flag==']'){
						wordss.push_back(token(s));
						s = string(1,a);
						flag = chcl(a);
					}else{
						s += string(1,a);
					}
				}else{
					s += string(1,a);
					flag = chcl(a);
				}
			}

			// 5. 澶勭悊琛屽熬娈嬬暀token锛堥潪瀛楃涓茬姸鎬佷笅锛?
			if(!s.empty() && !in_string){
				wordss.push_back(token(s));
			}
			// 6. 鑻ヨ灏句粛鍦ㄥ瓧绗︿覆鍐咃紙鏈棴鍚堝紩鍙凤級锛屼篃淇濆瓨褰撳墠鍐呭
			else if(!s.empty() && in_string){
				cerr<<"Warning: Unclosed string at line end: "<<s<<endl;
				wordss.push_back(token(s));
			}

			words.push_back(wordss);
		}
};//lexer.hpp 